﻿using System;
using System.Diagnostics;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Media;

namespace Chenglin.W8Timer
{
    public sealed partial class TimerTextControl : UserControl
    {
        private Stopwatch _stopWatch;
        private DispatcherTimer _timer;
        private DispatcherTimer _sliderShowTimer;
        private DateTime _lastMouseMove = DateTime.MinValue;

        public RoutedEventHandler ResetClick;

        /// <summary>
        /// Get or set a value indicating whether this is a timer or a count down timer?
        /// </summary>
        public bool IsCountDown
        {
            get;
            set;
        }

        /// <summary>
        /// Get or set the initial time.
        /// </summary>
        public TimeSpan StartTimeSpan
        {
            get;
            set;
        }

        public TimerTextControl()
        {
            this.InitializeComponent();
            StartTimeSpan = TimeSpan.Zero;
            IsCountDown = false;

            // Initialize the timers
            _timer = new DispatcherTimer();
            _timer.Interval = TimeSpan.FromMilliseconds(Constants.TimerInterval);
            _timer.Tick += OnTimerTick;

            _sliderShowTimer = new DispatcherTimer();
            _sliderShowTimer.Interval = TimeSpan.FromSeconds(5);
            _sliderShowTimer.Tick += OnSliderShowTimer_Tick;

            // Initialize the Stop Watch
            _stopWatch = new Stopwatch();
            this.Loaded += OnTimerTextControl_Loaded;
            this.Loaded += delegate { Window.Current.SizeChanged += OnWindowSizeChanged; };
            this.Unloaded += delegate { Window.Current.SizeChanged -= OnWindowSizeChanged; };
        }

        private Transform _lastTransformForTimerText;
        private Transform NoScaleTransform = new CompositeTransform { ScaleX = 1, ScaleY = 1 };
        private void OnWindowSizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
        {
            if (ApplicationView.Value == ApplicationViewState.Snapped)
            {
                _lastTransformForTimerText = this.panelText.RenderTransform;
                this.panelText.RenderTransform = NoScaleTransform;
            }
            else
            {
                this.panelText.RenderTransform = _lastTransformForTimerText;
            }
        }

        private void OnSliderShowTimer_Tick(object sender, object e)
        {
            if (DateTime.Now.Subtract(this._lastMouseMove) > TimeSpan.FromSeconds(5))
            {
                _sliderShowTimer.Stop();

                this.fadeInStoryboard.Stop();
                this.fadeOutStoryboard.Begin();
            }
        }

        private void OnTimerTextControl_Loaded(object sender, RoutedEventArgs e)
        {
            // Initialize the font size slider.
            const int InitialSliderValue = 10;

            this.fontSizeSlider.Minimum = 0;
            this.fontSizeSlider.Maximum = 100;
            this.fontSizeSlider.StepFrequency = 1;
            this.fontSizeSlider.Value = InitialSliderValue;

            this.fontSizeSlider.ValueChanged += delegate(object sliderSender, RangeBaseValueChangedEventArgs args)
            {
                double scaler = args.NewValue / InitialSliderValue;
                this.panelText.RenderTransform = new CompositeTransform { ScaleX = scaler, ScaleY = scaler };
            };

            this.PointerMoved += delegate
            {
                if (ApplicationView.Value != ApplicationViewState.Snapped)
                {
                    this._lastMouseMove = DateTime.Now;
                    this.fadeOutStoryboard.Stop();
                    this.fadeInStoryboard.Begin();

                    _sliderShowTimer.Start();
                }
            };
        }

        /// <summary>
        /// Start the timer, and update the associated UI elements.
        /// </summary>
        public void StartTimer(bool isCountDownMode, TimeSpan startTimeSpan)
        {
            IsCountDown = isCountDownMode;
            StartTimeSpan = startTimeSpan;

            // Start the timer/stop watch
            _timer.Start();
            _stopWatch.Start();

            // Update UI
            btnStart.Visibility = Visibility.Collapsed;
            btnPause.Visibility = Visibility.Visible;
            UpdateTimerText(startTimeSpan);
        }

        private void UpdateTimerText(TimeSpan ts)
        {
            tbSeconds.Text = string.Format("{0:00}:{1:00}:{2:00}", (int)ts.TotalHours, ts.Minutes, ts.Seconds);
            tbMilliseconds.Text = string.Format("{0:000}", ts.Milliseconds);
        }

        private void OnTimerTick(object sender, object e)
        {
            if (_timer.IsEnabled)
            {
                if (IsCountDown)
                {
                    TimeSpan ts = StartTimeSpan.Subtract(_stopWatch.Elapsed);
                    if (ts > TimeSpan.Zero)
                    {
                        UpdateTimerText(ts);
                    }
                    else
                    {
                        // Stop the timer/stop watch
                        _timer.Stop();
                        _stopWatch.Stop();
                        UpdateTimerText(TimeSpan.Zero);
                    }
                }
                else
                {
                    UpdateTimerText(_stopWatch.Elapsed);
                }
            }
        }

        private void OnStartClick(object sender, RoutedEventArgs e)
        {
            _timer.Start();
            _stopWatch.Start();

            btnStart.Visibility = Visibility.Collapsed;
            btnPause.Visibility = Visibility.Visible;
        }

        private void OnPauseClick(object sender, RoutedEventArgs e)
        {
            _stopWatch.Stop();
            _timer.Stop();

            btnStart.Visibility = Visibility.Visible;
            btnPause.Visibility = Visibility.Collapsed;
        }

        private void OnResetClick(object sender, RoutedEventArgs e)
        {
            // Stop Stopwach
            _stopWatch.Stop();
            _stopWatch.Reset();

            //Stop timer
            _timer.Stop();

            // Also reset UI
            UpdateTimerText(StartTimeSpan);

            RoutedEventHandler handler = ResetClick;
            if (handler != null)
            {
                handler(sender, e);
            }
        }
    }
}
